package br.com.rapidrest.chain;

import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import br.com.rapidrest.exception.ChainException;
import br.com.rapidrest.request.RequestScope;

public class RequestScopeCommand implements Command {

	private static final Pattern SPLIT_REGEX = Pattern.compile("/");

	public static final String START_PAGE_ATTRIBUTE = "rapidRest.start.page";

	@Override
	public void execute(Chain chain) throws ChainException {
		BasicChainContext context = (BasicChainContext) chain.getContext();
		HttpServletRequest request = context.getRequest();
		String contextPath = request.getContextPath();
		String requestURI = request.getRequestURI();
		requestURI = requestURI.replace(contextPath, "");
		if (requestURI.equals("/")) {
			String startPage = request.getSession().getServletContext()
					.getInitParameter(START_PAGE_ATTRIBUTE);
			if (startPage != null) {
				try {
					context.getResponse().sendRedirect(startPage);
				} catch (IOException e) {
					throw new ChainException(e);
				}
			} else {
				chain.getCommands().clear();
				chain.proceed();
			}
		}
		String webPackage = context.getWebPackage();
		RequestScope requestScope = buildRequestScope(requestURI, webPackage);

		if (requestScope != null) {
			context.setRequestScope(requestScope);
			chain.proceed();
		} else {
			try {
				context.getResponse().sendError(404);
			} catch (IOException e) {
				throw new ChainException(e);
			}
		}
	}

	static RequestScope buildRequestScope(String uri, String webPackage) {
		RequestScope requestScope = new RequestScope();

		uri = uri.substring(1);

		String[] paths = SPLIT_REGEX.split(uri);

		StringBuilder classNameBuilder = new StringBuilder(webPackage);

		final String dot = ".";
		int index = 0;
		for (; index < paths.length; index++) {
			String path = paths[index];
			if (Character.isUpperCase(path.charAt(0))) {
				int firstIndexOf = path.indexOf(dot);
				if (firstIndexOf > 0) {
					String methodName = path.substring(firstIndexOf + 1);
					requestScope.setMethodName(methodName);
					path = path.substring(0, firstIndexOf);
				}
				classNameBuilder.append(dot).append(path);
				break;
			}
			classNameBuilder.append(dot).append(path);
		}

		try {
			Class<?> beanClass = Class.forName(classNameBuilder.toString());
			requestScope.setBeanClass(beanClass);
		} catch (ClassNotFoundException e) {
			return null;
		}

		if (index + 1 < paths.length) {
			String[] params = Arrays
					.copyOfRange(paths, index + 1, paths.length);

			requestScope.setParams(params);
		}

		return requestScope;
	}

}
